home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
c
/
tagsgen.exe
/
SORT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-02
|
50KB
|
1,827 lines
/* sort.c - sort lines of text (with all kinds of options).
Copyright 1989 Free Software Foundation
Written December 1988 by Mike Haertel.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author may be reached (Email) at the address mike@ai.mit.edu,
or (US mail) as Mike Haertel c/o Free Software Foundation. */
/* MS-DOS port (c) 1990 by Thorsten Ohl, td12@ddagsi3.bitnet
This port is also distributed under the terms of the
GNU General Public License as published by the
Free Software Foundation.
$Header: e:/gnu/sort/RCS/sort.c'v 0.3.0.4 90/08/26 19:03:05 tho Exp $
*/
static char version[] = "GNU sort, version 0.3";
#include "std.h"
#ifndef MSDOS
#include "unix.h"
#endif /* not MSDOS */
#ifdef SORT_MODULE
#include "sort.h"
#endif
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#ifdef MSDOS
#include <process.h>
static void cleanup (void);
static void assert_lines (int lines);
void *xmalloc (unsigned int size);
void *xrealloc (void *ptr, unsigned int size);
static FILE *xfopen (char *file, char *how);
static void xfclose (FILE *fp);
static void xfwrite (char *buf, int size, int nelem, FILE *fp);
static char *tempname (void);
static void zaptemp (char *name);
static void inittables (void);
static void initbuf (struct buffer *buf, int alloc);
static int fillbuf (struct buffer *buf, FILE *fp);
static void initlines (struct lines *lines, int alloc);
static char *begfield (struct line *line, struct keyfield *key);
static char *limfield (struct line *line, struct keyfield *key);
static void findlines (struct buffer *buf, struct lines *lines);
static int fraccompare (char *a, char *b);
static int numcompare (char *a, char *b);
static int getmonth (char *s, int len);
static int keycompare (struct line *a, struct line *b);
static int compare (struct line *a, struct line *b);
static int checkfp (FILE *fp);
static void mergefps (FILE **fps, int nfps, FILE *ofp);
static void sortlines (struct line *lines, int nlines, struct line *temp);
static int check (char **files, int nfiles);
static void merge (char **files, int nfiles, FILE *ofp);
static void sort (char **files, int nfiles, FILE *ofp);
static void insertkey (struct keyfield *key);
static void usage (void);
static void badfieldspec (char *s);
static void inthandler (void);
#ifndef SORT_MODULE
int main (int argc, char **argv);
#endif
#endif /* MSDOS */
/* A few useful macros. */
#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define UCHAR_LIM (UCHAR_MAX + 1)
#define UCHAR(c) ((unsigned char) (c))
/* Table of digits. */
static int digits[UCHAR_LIM];
/* Table of white space. */
static int blanks[UCHAR_LIM];
/* Table of non-printing characters. */
static int nonprinting[UCHAR_LIM];
/* Table of non-dictionary characters (not letters, digits, or blanks). */
static int nondictionary[UCHAR_LIM];
/* Translation table folding upper case to lower. */
static char fold_tolower[UCHAR_LIM];
/* Table mapping 3-letter month names to integers.
Alphabetic order allows binary search. */
static struct month {
char *name;
int val;
} monthtab[] = {
"apr", 4,
"aug", 8,
"dec", 12,
"feb", 2,
"jan", 1,
"jul", 7,
"jun", 6,
"mar", 3,
"may", 5,
"nov", 11,
"oct", 10,
"sep", 9
};
/* During the merge phase, the number of files to merge at once. */
#ifdef MSDOS
/* 14 (= 20 - 5 - 1) is a hard upper limit for MeSsy DOS versions <3.2
(and a soft one for later versions...) */
#define NMERGE 12
#else /* not MSDOS */
#define NMERGE 16
#endif /* not MSDOS */
/* Initial buffer size for in core sorting. Will not grow unless a
line longer than this is seen. */
#ifdef MSDOS
static int sortalloc = 32767;
#else /* not MSDOS */
static int sortalloc = 524288;
#endif /* not MSDOS */
/* Initial buffer size for in core merge buffers. Bear in mind that
up to NMERGE * mergealloc bytes may be allocated for merge buffers. */
static int mergealloc = 16384;
/* Guess of average line length. */
static int linelength = 30;
/* Prefix for temporary file names. */
#ifdef MSDOS
static char *prefix;
#else /* not MSDOS */
static char *prefix = "/tmp";
#endif /* not MSDOS */
/* Flag to reverse the order of all comparisons. */
static int reverse;
/* Tab character separating fields. If NUL, then fields are separated
by the empty string between a non-whitespace character and a whitespace
character. */
static char tab;
/* Flag to remove consecutive duplicate lines from the output.
Only the last of a sequence of equal lines will be output. */
static int unique;
/* Lines are held in core as counted strings. */
struct line
{
char *text; /* Text of the line. */
int length; /* Length not including final newline. */
char *keybeg; /* Start of first key. */
char *keylim; /* Limit of first key. */
};
#ifdef MSDOS
/* Using _huge line arrays under MS-DOS is terribly inefficient, so we
impose an upper limit on the number of lines cosidered at once. The
user can break the input into digestable pieces by using the `-S' option
to adjust the input buffer size.
This only matters for files with very short lines ( < 8 chars). */
static int maxlines
= (int) (((1L << 16) - 1L) / sizeof (struct line));
void
assert_lines (int lines)
{
if (lines >= maxlines)
{
fprintf (stderr,
"sort: the number of lines per input buffer is restricted in\n"
" the MS-DOS version. For files with short lines, use\n"
" the `-S <num>' option to reduce the buffer size.\n");
cleanup ();
#ifdef SORT_MODULE
external_cleanup();
#endif
exit (-1);
}
}
#endif /* MSDOS */
/* Arrays of lines. */
struct lines
{
struct line *lines; /* Dynamically allocated array of lines. */
int used; /* Number of slots used. */
int alloc; /* Number of slots allocated. */
};
/* Input buffers. */
struct buffer
{
char *buf; /* Dynamically allocated buffer. */
int used; /* Number of bytes used. */
int alloc; /* Number of bytes allocated. */
int left; /* Number of bytes left after line parsing. */
};
/* Lists of key field comparisons to be tried. */
static struct keyfield
{
int sword; /* Zero-origin 'word' to start at. */
int schar; /* Additional characters to skip. */
int skipsblanks; /* Skip leading white space at start. */
int eword; /* Zero-origin first word after field. */
int echar; /* Additional characters in field. */
int skipeblanks; /* Skip trailing white space at finish. */
int *ignore; /* Boolean array of characters to ignore. */
char *translate; /* Translation applied to characters. */
int numeric; /* Flag for numeric comparison. */
int month; /* Flag for comparison by month name. */
int reverse; /* Reverse the sense of comparison. */
struct keyfield *next; /* Next keyfield to try. */
} keyhead;
/* The list of temporary files. */
static struct tempnode
{